<template>
    <div v-if="show" class="cut-image__wrapper">
        <el-card class="cut-image__module" :header="title" shadow="naver">
            <section class="workbench__group clearfix">
                <div class="cut-block__group fl">
                    <div class="title__item">截图展示区域</div>
                    <div class="box__wrapper">
                        <div :style="bgWrapperStyle" class="bg__wrapper">
                            <div
                                :style="imageWrapperStyle"
                                class="image__wrappaer"
                                v-show="nowShowImage"
                            >
                                <img
                                    :src="nowShowImage"
                                    draggable="false"
                                    ref="image"
                                    style="opacity:.5"
                                />
                                <div :style="checkBoxStyle" class="check-box__item" ref="checkBox">
                                    <img
                                        :src="nowShowImage"
                                        :style="checkImageStyle"
                                        draggable="false"
                                    />
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="preview-block__group fr">
                    <div class="title__item">最终展示效果</div>
                    <div class="preview-image__item">
                        <img :src="nowShowImage" :style="previewImageStyle" />
                    </div>
                </div>
            </section>
            <div class="controller__group">
                <el-button class="re-check-image__btn" plain round size="small" type="info">
                    重新选择
                    <input :accept="accept" @change="reCheckHandler" type="file" />
                </el-button>
                <el-button @click="submit(true)" plain round size="small" type="primary">确认</el-button>&nbsp;&nbsp;
                <el-button @click="$emit('cancel')" plain round size="small" type="info">取消</el-button>
            </div>
            <canvas height="540" ref="canvas" v-show="false" width="960" />
        </el-card>
    </div>
</template>

<script>
import { base64ToBlob, translateBase64ImgToFile } from "@/utils/index";

export default {
    name: "CurCoverModule",
    props: {
        title: {
            type: String,
            default: "标题",
        },
        show: {
            type: [String, Boolean],
            default: true,
        },
        image: {
            type: [String, File],
            required: true,
            default: "",
        },
        accept: {
            type: [String, File],
            default: "image/jpeg, image/jpg, image/png, image/bmp",
        },
    },
    data() {
        return {
            newImage: "",
            imageFile: this.image,
            containerW: 480,
            containerH: 300,
            previewW: 240,
            previewH: 135,
            imageW: 0,
            imageH: 0,
            isWidth: null,
            startPoint: { x: 0, y: 0 },
            checkBoxMovePoint: { x: 0, y: 0 },
        };
    },
    computed: {
        nowShowImage() {
            return this.newImage || window.URL.createObjectURL(this.image);
        },
        bgWrapperStyle() {
            return {
                width: `${this.containerW}px`,
                height: `${this.containerH}px`,
            };
        },
        rawImageDiff() {
            return this.imageW / this.imageH;
        },
        imageWrapperStyle() {
            if (this.imageW === 0 || this.imageH === 0) return {};
            let width = 0;
            let height = 0;
            if (this.isWidth) {
                width = this.containerW;
                height = this.containerW / this.rawImageDiff;
            } else {
                width = this.containerH * this.rawImageDiff;
                height = this.containerH;
            }
            return {
                width: `${width}px`,
                height: `${height}px`,
            };
        },
        checkBoxStyle() {
            let width = 0;
            let height = 0;
            if (this.isWidth) {
                height = this.containerW / this.rawImageDiff;
                width = height * (16 / 9);
            } else {
                width = this.containerH * this.rawImageDiff;
                height = width / (16 / 9);
            }
            return {
                width: `${width}px`,
                height: `${height}px`,
                transform: `translate(${this.checkBoxMovePoint.x}px, ${this.checkBoxMovePoint.y}px)`,
            };
        },
        checkImageStyle() {
            return {
                ...this.imageWrapperStyle,
                transform: `translate(-${this.checkBoxMovePoint.x}px, -${this.checkBoxMovePoint.y}px)`,
            };
        },
        previewImageStyle() {
            let width = 0;
            let height = 0;
            const transform = { x: 0, y: 0 };
            if (this.isWidth) {
                width = this.previewH * this.rawImageDiff;
                height = this.previewH;
            } else {
                width = this.previewW;
                height = this.previewW / this.rawImageDiff;
            }
            transform.x = width / (this.containerW / this.checkBoxMovePoint.x);
            transform.y = height / (this.containerH / this.checkBoxMovePoint.y);
            return {
                width: `${width}px`,
                height: `${height}px`,
                transform: `translate(-${transform.x}px, -${transform.y}px)`,
            };
        },
        curImageStyle() {
            let width = 0;
            let height = 0;
            if (this.isWidth) {
                width = 960 * this.rawImageDiff;
                height = 540;
            } else {
                width = 960;
                height = 960 / this.rawImageDiff;
            }
            return {
                width: `${width}px`,
                height: `${height}px`,
            };
        },
    },
    mounted() {
        this.main();
    },
    destroyed() {
        this.checkBoxUnBindMouseDrang();
    },
    methods: {
        async main() {
            this.imageReSize();
            this.checkBoxBindMouseDrang();
        },
        imageReSize() {
            return new Promise((resolve) => {
                this.$refs.image.addEventListener("load", () => {
                    const image = new Image(); // 这么做是为了在更换图的时候重新计算图片比例
                    image.onload = () => {
                        const { offsetWidth, offsetHeight } = image;
                        this.imageW = offsetWidth;
                        this.imageH = offsetHeight;
                        this.isWidth = offsetWidth / offsetHeight > 16 / 9;
                        if (offsetWidth / offsetHeight === 16 / 9) {
                            this.isWidth = true;
                        }
                        this.startPoint = { x: 0, y: 0 };
                        this.checkBoxMovePoint = { x: 0, y: 0 };
                        image.remove();
                        resolve();
                    };
                    image.src = this.nowShowImage;
                    document.body.append(image);
                });
            });
        },
        checkBoxBindMouseDrang() {
            const item = this.$refs.checkBox;
            item.addEventListener("mousedown", this.checkBoxBindMouseDonw);
            window.addEventListener("mouseup", this.checkBoxBindMouseUp);
        },
        checkBoxUnBindMouseDrang() {
            window.removeEventListener("mouseup", this.checkBoxBindMouseUp);
        },
        checkBoxBindMouseDonw(evt) {
            this.$refs.checkBox.addEventListener(
                "mousemove",
                this.checkBoxBindMouseMove,
            );
            this.startPoint.x = evt.clientX;
            this.startPoint.y = evt.clientY;
        },
        checkBoxBindMouseMove(evt) {
            const { x: copyX, y: copyY } = this.checkBoxMovePoint;
            // 计算移动差值
            let diffX = evt.clientX - this.startPoint.x;
            let diffY = evt.clientY - this.startPoint.y;
            // X轴的判断
            if (!this.isWidth) diffX = 0; // 限制X轴移动
            if (copyX + diffX < 0) diffX = 0; // 左靠边
            if (
                copyX + diffX
                > this.containerW
                    - (this.containerW / this.rawImageDiff) * (16 / 9)
            ) {
                diffX = 0;
            } // 右靠边
            // Y轴的判断
            if (this.isWidth) diffY = 0; // 限制Y轴移动
            if (copyY + diffY < 0) diffY = 0; // 上靠边
            if (
                copyY + diffY
                > this.containerH - (this.containerH * this.rawImageDiff) / (16 / 9)
            ) {
                diffY = 0;
            } // 下靠边
            // 移动选择框
            this.checkBoxMovePoint.x += diffX;
            this.checkBoxMovePoint.y += diffY;
            // 初始化起始点
            this.startPoint.x = evt.clientX;
            this.startPoint.y = evt.clientY;
        },
        checkBoxBindMouseUp() {
            this.$refs.checkBox.removeEventListener(
                "mousemove",
                this.checkBoxBindMouseMove,
            );
        },
        reCheckHandler(evt) {
            const file = evt.target.files[0];
            if (this.accept.indexOf(`${file.type}`) === -1) {
                this.$message.error("文件格式不正确!");
            } else {
                this.imageFile = file;
                this.newImage = window.URL.createObjectURL(file);
                this.imageReSize();
            }
            // eslint-disable-next-line no-param-reassign
            evt.target.value = null;
        },
        submit() {
            const { canvas, image } = this.$refs;
            const ctx = canvas.getContext("2d");
            let width = 0;
            let height = 0;
            const path = { x: 0, y: 0 };
            if (this.isWidth) {
                width = 540 * this.rawImageDiff;
                height = 540;
            } else {
                width = 960;
                height = 960 / this.rawImageDiff;
            }
            path.x = width / (this.containerW / this.checkBoxMovePoint.x);
            path.y = height / (this.containerH / this.checkBoxMovePoint.y);
            // 填充画布背景色
            ctx.fillStyle = "#000";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            // 绘制截图
            ctx.drawImage(image, -path.x, -path.y, width, height);
            // const result = canvas.toDataURL("image/png"); // 绘制为png
            const result = canvas.toDataURL("image/jpeg"); // 绘制为jpg
            const fileObj = this.base64ToFileHandler(result);
            this.$emit("cutComplete", fileObj);
        },
        base64ToFileHandler(base64Data) {
            const blob = base64ToBlob(base64Data);
            const file = translateBase64ImgToFile(
                base64Data,
                this.imageFile.name,
                this.imageFile.type,
            );
            return { blob, file };
        },
    },
};
</script>

<style lang="scss">
.cut-image__module {
    width: 840px;
    font-size: 14px;

    img {
        width: 100%;
        height: 100%;
        pointer-events: none;
        user-select: none;
    }

    .workbench__group {
        padding-bottom: 50px;
    }

    .title__item {
        margin-bottom: 10px;
        font-size: 12px;
        color: #99a2aa;
    }

    .cut-block__group {
        width: 500px;
    }

    .box__wrapper {
        padding-right: 20px;
        border-right: 1px solid #e5e9ef;

        .bg__wrapper {
            border-radius: 4px;
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: #000;
            overflow: hidden;
        }

        .image__wrappaer {
            position: relative;
            margin: auto;
        }

        .check-box__item {
            position: absolute;
            top: 0;
            left: 0;
            box-shadow: 0 0 0 1px #fff;
            overflow: hidden;
            cursor: move;
        }
    }

    .preview-block__group {
        width: 240px;

        .preview-image__item {
            width: 240px;
            height: 135px;
            // border-radius: 4px;
            overflow: hidden;
            box-shadow: 0 1px 3px 0 #d0d5de;
            background: #000;
        }
    }

    .controller__group {
        border-top: 1px solid #e5e9ef;
        position: relative;
        padding-top: 20px;
        text-align: center;
    }

    .re-check-image__btn {
        margin-bottom: 10px;
        position: absolute;
        bottom: 100%;
        left: 0;
        input {
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
            opacity: 0;
            cursor: pointer;
        }
    }
}

.cut-image__wrapper {
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 2001;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgba($color: #000000, $alpha: 0.5);
}
</style>
